package com.vip8.recorder.service.utils;

import com.alibaba.druid.util.Base64;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.Base64Utils;

import javax.crypto.Cipher;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

@Slf4j
public class OpenApiRsaUtils {
    private static final String KEY_ALGORITHM = "RSA";
    private static final int DEFAULT_KEY_SIZE = 1024;
    /*** 获取公钥的key */
    private static final String PUBLIC_KEY = "RSAPublicKey";
    /*** 获取私钥的key */
    private static final String PRIVATE_KEY =
            "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMUWT8xVuOgvl4uq"
            + "RqS4lsFWD/KdIbckfZ5Yx0cJ2T3rsXGrjTqmAHf+Y1y6s0nEYx9uAwb208XGFzBI"
            + "Y4GWMOIpMGMwEzBvDBIQZ7EPyH+K6mTL9834cZnNH+4JY8wmoY94BaHmQGEJTw2S"
            + "KId5HAIhJYgY3AngtOPT7Bof2uLRAgMBAAECgYEAqSGxj0gNK2wUIC4a+6bQ8M9b"
            + "VjfURCeTibzkHqlr/cBzAXpX83mbs13ihSRPUcGv0rwE6wgMyo9pPO0SP5XVEe6i"
            + "qmN56qgkVO8pvjc5YSaUb9xAzCdebEOqJ80YjjGMHB9n720BUhx4wdMPayQFWVj5"
            + "4j6kKGeuZiA31YRykmUCQQDqvthU6wj/Ep2wkpmxyXY7pHmuicFPp1j7LNJtOIHO"
            + "cYu1cw+Vvcd/7z3BPw/pl/zqqknej1BbwBIIiRkkrbH/AkEA1u6V/BQz5mr7TovE"
            + "vgmO+qpX+T6Law9XuqftdAeEJK10rgL5tbUyjVy+FBBs4Uc17f8zLGkDn8D/aQM3"
            + "VC7LLwJAQFScpGjkxkIrxL/oLrivFhk034gQ2etajzrxT800hYbIaqllk/u2OHEv"
            + "002c5r8oKIcSR1OvCfXQ+1XW9h5DsQJAEKj9x0RpoXq5cCU1YuWqx5Ncrl1CwVG3"
            + "IyjRJyVOAOnRGYvxfzxEZuDBexyq0+uJKqGVfePF/CQhqCovp77Y0QJBAOHtLny+"
            + "BAUJlQXY2Tn1j/u0r31W6Z78aQdsW88fyNVzCIVQaetW1wZusaAAyLRaIc3iZxXP"
            + "5daC1jXDw4BGzd4=";
    /**
     * 签名算法
     */
    private static final String SIGNATURE_ALGORITHM = "MD5withRSA";

    public static Map<String, Object> initKey() throws Exception {
        return initKey(DEFAULT_KEY_SIZE);
    }

    /*** ⽣成秘钥对（公钥和私钥） ** @param keySize * @return * @throws Exception */
    public static Map<String, Object> initKey(int keySize) throws Exception {
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
        keyPairGen.initialize(keySize);
        KeyPair keyPair = keyPairGen.generateKeyPair();
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
        Map<String, Object> keyMap = new HashMap<>(2);
        keyMap.put(PUBLIC_KEY, publicKey);
        keyMap.put(PRIVATE_KEY, privateKey);
        return keyMap;
    }

    /*** 私钥加密 ** @param data 源数据 * @param privateKey 私钥(BASE64编码) * @return * @throws Exception */
    public static byte[] encryptByPrivateKey(byte[] data, String privateKey) throws Exception {
        try {
            byte[] encodedKey = Base64.base64ToByteArray(privateKey);
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encodedKey);
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
            PrivateKey privateK = keyFactory.generatePrivate(keySpec);
            return encrypt(data, keyFactory, privateK);
        } catch (InvalidKeySpecException | NoSuchAlgorithmException e) {
            log.error("RSAUtils encryptByPrivateKey exception:{}", e.getMessage());
            throw new RuntimeException(e);
        }
    }

    /*** 加密公共⽅法 ** @param data * @param keyFactory * @param key * @return * @throws Exception */
    private static byte[] encrypt(byte[] data, KeyFactory keyFactory, Key key) throws Exception {
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, key);
        return cipher.doFinal(data);
    }

    /*** ⽤私钥对信息⽣成数字签名 ** @param data * @param privateKey * @return * @throws Exception */
    public static String sign(byte[] data, String privateKey) throws Exception {
        byte[] encodedKey = Base64.base64ToByteArray(privateKey);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encodedKey);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        PrivateKey privateK = keyFactory.generatePrivate(keySpec);
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        signature.initSign(privateK);
        signature.update(data);
        return Base64Utils.encodeToString(signature.sign());
    }

    public static String sign(byte[] data) throws Exception {
        return sign(data, PRIVATE_KEY);
    }

    /*** 校验数字签名 ** @param data 已加密数据 * @param publicKey 公钥(BASE64编码) * @param sign 数字签名 * @return * @throws Exception */
    public static boolean verify(String data, String publicKey, String sign) throws Exception {
        byte[] keyBytes = Base64.base64ToByteArray(publicKey);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        PublicKey publicK = keyFactory.generatePublic(keySpec);
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        signature.initVerify(publicK);
        byte[] paramsKeys = data.getBytes();
        signature.update(paramsKeys);
        try {
            return signature.verify(Base64.base64ToByteArray(sign));
        } catch (Exception e) {
            log.error("RSAUtils verify fail,e：{}", e.getMessage());
            return false;
        }
    }

    /*** 获取私钥 ** @param keyMap 密钥对 * @return * @throws Exception */
    public static String getPrivateKey(Map<String, Object> keyMap) {
        Key key = (Key) keyMap.get(PRIVATE_KEY);
        return Base64Utils.encodeToString(key.getEncoded());
    }

    /*** 获取公钥 ** @param keyMap 密钥对 * @return * @throws Exception */
    public static String getPublicKey(Map<String, Object> keyMap) {
        Key key = (Key) keyMap.get(PUBLIC_KEY);
        return Base64Utils.encodeToString(key.getEncoded());
    }

    public static void main(String[] args) throws Exception {
        //shi zi
        String s = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMUWT8xVuOgvl4uq" + "RqS4lsFWD/KdIbckfZ5Yx0cJ2T3rsXGrjTqmAHf+Y1y6s0nEYx9uAwb208XGFzBI" + "Y4GWMOIpMGMwEzBvDBIQZ7EPyH+K6mTL9834cZnNH+4JY8wmoY94BaHmQGEJTw2S" + "KId5HAIhJYgY3AngtOPT7Bof2uLRAgMBAAECgYEAqSGxj0gNK2wUIC4a+6bQ8M9b" + "VjfURCeTibzkHqlr/cBzAXpX83mbs13ihSRPUcGv0rwE6wgMyo9pPO0SP5XVEe6i" + "qmN56qgkVO8pvjc5YSaUb9xAzCdebEOqJ80YjjGMHB9n720BUhx4wdMPayQFWVj5" + "4j6kKGeuZiA31YRykmUCQQDqvthU6wj/Ep2wkpmxyXY7pHmuicFPp1j7LNJtOIHO" + "cYu1cw+Vvcd/7z3BPw/pl/zqqknej1BbwBIIiRkkrbH/AkEA1u6V/BQz5mr7TovE" + "vgmO+qpX+T6Law9XuqftdAeEJK10rgL5tbUyjVy+FBBs4Uc17f8zLGkDn8D/aQM3" + "VC7LLwJAQFScpGjkxkIrxL/oLrivFhk034gQ2etajzrxT800hYbIaqllk/u2OHEv" + "002c5r8oKIcSR1OvCfXQ+1XW9h5DsQJAEKj9x0RpoXq5cCU1YuWqx5Ncrl1CwVG3" + "IyjRJyVOAOnRGYvxfzxEZuDBexyq0+uJKqGVfePF/CQhqCovp77Y0QJBAOHtLny+" + "BAUJlQXY2Tn1j/u0r31W6Z78aQdsW88fyNVzCIVQaetW1wZusaAAyLRaIc3iZxXP" + "5daC1jXDw4BGzd4=";
        Long kt = System.currentTimeMillis() / 1000;
        String format = "kf_data={\n" + " \"method\": \"usercenter.backend.getEmployeeInfoByPhone\",\n" + " \"token\":\"c102f1d9-0689-4660-a041-01ddd2338708\",\n" + " \"appKey\":\"jly\",\n" + " \"data\": {\"phone\":\"LZUiDc2FDKom38wPuM5dmzUyLdg0HStgWPUp7rDg8UJr87wFo8N/78CbsRR3lf5IMWv9PpFxU2KyNj8UHsHXYA==\"}\n" + "}&kf_t=" + kt;
        System.out.println(format);
        String sign = sign(format.getBytes(StandardCharsets.UTF_8));
        System.out.println(sign);
    }
}